﻿using System;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Forms.VisualStyles;

using gKodes.IO;
using gKodes.Drawing;
using gKodes.Collections;

namespace gKodes.Windows.Forms
{
    public abstract class ControlPage : Control
    {
        /// <summary>
        /// Used for stroing the Content Rectangle of the Page
        /// </summary>
        private Rectangle mContentRect;

        /// <summary>
        /// Used for storing the String Format that needs to be applied while drawing on the Page
        /// </summary>
        private StringFormat msFormat;

        /// <summary>
        /// Used for stroing the Graphics Object of the page
        /// </summary>
        private Graphics mGraphics;

        /// <summary>
        /// Used for stroing the Paint Schemen Collection Object
        /// </summary>
        private PaintSchemeCollection mpSchemes;

        private SegmentCollection mpSegments;

        private PageSegment mpIFocus;

        private bool msOverflow;

        private int mOverflow;

        public new string CompanyName
        {
            get { return "gKodes (@gKodes.net)"; }
        }

        protected StringFormat StringFormat
        {
            get { return this.msFormat; }
        }

        public Size PageSize
        {
            get { return this.ClientSize; }
        }

        public PaintSchemeCollection PaintSchemes
        {
            get { return this.mpSchemes; }
        }

        protected virtual SegmentCollection Segments
        {
            get { return this.mpSegments; }
        }

        protected virtual Graphics Graphics//IPage.
        {
            get { return this.mGraphics; }
        }

        public bool IsOverflow
        {
            get { return this.msOverflow; }
        }

        public override Color ForeColor
        {
            get { return (this.mpSchemes != null) ? this.mpSchemes[0].Foreground.Color : base.ForeColor; }
            set {
                this.mpSchemes.ChangeForePaint(0, (SolidPaint)value);
                base.ForeColor = value;
            }
        }

        public override Color BackColor
        {
            get { return (this.mpSchemes != null) ? this.mpSchemes[0].Foreground.Color : base.BackColor; }
            set
            {
                this.mpSchemes.ChangeBackPaint(0, (SolidPaint)value);
                base.BackColor = value;
            }
        }

        protected PageSegment InFocusSegment
        {
            get { return this.mpIFocus; }
        }
        
        /// <summary>
        /// Gets or sets a value indicating whether the horizontal scroll bar is visible.
        /// </summary>
        protected internal readonly HScrollBar HScroll;

        /// <summary>
        /// Gets or sets a value indicating whether the vertical scroll bar is visible.
        /// </summary>
        protected internal readonly VScrollBar VScroll;

        public event ScrollEventHandler Scroll;

        public event SegmentEvent SegmentFocusChanged;

        public event EventHandler PageValidating;

        public event EventHandler PageInvalidated;

        public ControlPage()
            : base()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | 
                 ControlStyles.Selectable | ControlStyles.UserMouse, true);

            this.mpSchemes = new PaintSchemeCollection();
            this.mpSchemes.Change(0, (SolidPaint)base.ForeColor, (SolidPaint)base.BackColor);
            this.BackColor = SystemColors.Window;
            this.mpSegments = new SegmentCollection(this);
            this.msOverflow = false;
            this.mOverflow = 0;

            this.VScroll = new VScrollBar();
            this.VScroll.Name = "hv.VScrollBar";
            this.VScroll.LargeChange = 1;
            this.VScroll.Scroll += new ScrollEventHandler(Bar_Scroll);
            this.VScroll.Visible = false;
            this.HScroll = new HScrollBar();
            this.HScroll.Name = "hv.HScrollBar";
            this.HScroll.LargeChange = 1;
            this.HScroll.Scroll += new ScrollEventHandler(Bar_Scroll);
            this.HScroll.Visible = false;

            this.msFormat = StringFormat.GenericTypographic;
            this.msFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
            this.msFormat.Alignment = StringAlignment.Near;
            this.msFormat.LineAlignment = StringAlignment.Near;
            this.msFormat.Trimming = StringTrimming.Word;

            this.SuspendLayout();
            this.Controls.Add(this.VScroll);
            this.Controls.Add(this.HScroll);
            this.ResumeLayout();
        }

        public virtual void InvalidatePage()
        {
            this.InvalidatePage(this.ClientRectangle);
            this.Invalidate();
        }

        protected void InvalidatePage(Rectangle mcrect)//virtual 
        {
            if (this.PageValidating != null)
                this.PageValidating(this, EventArgs.Empty);

            this.mContentRect = new Rectangle(
                mcrect.X + this.Padding.Left, this.Padding.Top + mcrect.Y,
                mcrect.Width - this.Padding.Horizontal, mcrect.Height - this.Padding.Vertical);

            if (this.VScroll.Visible)
                this.mContentRect.Width -= this.VScroll.Width;

            if (this.HScroll.Visible)
                this.mContentRect.Height -= this.HScroll.Height;

            this.VScroll.Location = new Point(this.mContentRect.Right, this.mContentRect.Y);
            this.HScroll.Location = new Point(this.mContentRect.X, this.mContentRect.Bottom);

            this.VScroll.Height = this.mContentRect.Height;
            this.HScroll.Width = this.mContentRect.Width;

            Size tSize = this.mContentRect.Size;
            Point tPoint = this.mContentRect.Location;
            this.msOverflow = false;
            for (int i = 0; i < this.mpSegments.Count; i++)
            {
                if (this.mpSegments[i].Visible)
                {
                    //TODO: update page segments
                    this.mpSegments[i].Location = tPoint;
                    this.mpSegments[i].OnSizeChanged(tSize);
                    tSize.Width -= this.mpSegments[i].DisplayRectangle.Width;
                    tPoint.X += this.mpSegments[i].DisplayRectangle.Width;
                    if (this.mpSegments[i].ClientRectangle.Height > this.mContentRect.Height)
                        this.msOverflow = true;
                    //this.mpSegments[i].OnSizeChanged(this.mContentRect.Size);
                }
            }

            if (this.PageInvalidated != null)
                this.PageInvalidated(this, EventArgs.Empty);
        }

        protected virtual int Register(PageSegment psegments)
        {
            this.mpSegments.Add(psegments);
            return this.mpSegments.Count - 1;
        }

        protected virtual void UnRegister(int psid)
        {
            this.mpSegments.RemoveAt(psid);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            this.mGraphics = e.Graphics;
            foreach (PageSegment ps in this.mpSegments)
            {
                if (ps.Visible)
                {
                    Rectangle sBox = new Rectangle(ps.Location, ps.DisplayRectangle.Size);
                    if (e.ClipRectangle.IntersectsWith(sBox))
                    {
                        this.Graphics.TranslateTransform(ps.Location.X, ps.Location.Y);
                        Rectangle rec = Rectangle.Intersect(e.ClipRectangle, sBox);
                        rec.Location -= (Size)ps.Location;
                        this.Graphics.SetClip(rec);
                        ps.RenderSegment(rec);
                        //ps.RenderSegment(ps.DisplayRectangle);

                        this.Graphics.ResetClip();
                        this.Graphics.ResetTransform();
                    }
                }
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            //Info: update the Client area & ContentArea Size
            this.InvalidatePage();
        }

        protected override void OnPaddingChanged(EventArgs e)
        {
            //Info: update the ContentArea rectangle
            base.OnPaddingChanged(e);
            this.InvalidatePage();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            //Info: get the segment in which the mouse was pressed down
            foreach (PageSegment ps in this.mpSegments)
            {
                if (ps.CanSelect && IsInSegment(ps, e.Location) &&
                        this.mpIFocus != ps)
                {
                    //Info: fire event on Segment focus changed
                    this.OnSegmentFocusChanged(new SegmentEventArgs(ps));
                }
            }
            base.OnMouseDown(e);
        }

        public static Point PageToSegment(PageSegment ps, Point pt)
        {
            return new Point(pt.X - ps.Location.X, pt.Y - ps.Location.Y);
        }

        private static bool IsInSegment(PageSegment ps, Point pt)
        {
            Point ipt = PageToSegment(ps, pt);
            return ((ipt.X > -1 && ipt.Y > -1) &&
                    ipt.X < ps.DisplayRectangle.Width && ipt.X < ps.DisplayRectangle.Height);
        }

        protected virtual void OnSegmentFocusChanged(SegmentEventArgs e)
        {
            this.mpIFocus = e.Segment;
#if DEBUG
            System.Diagnostics.Debug.WriteLine("OnSegmentFocusChanged : " + e.Segment.Name);
#endif
            if (this.SegmentFocusChanged != null)
                this.SegmentFocusChanged(this, e);
        }

        protected virtual void OnSegmentAdded(SegmentEventArgs e)
        {
            e.Segment.DrawnOn = this;
            e.Segment.Visible = true;
            this.InvalidatePage();
        }

        protected virtual void OnSegmentRemoved(SegmentEventArgs e)
        {
            e.Segment.DrawnOn = null;
            e.Segment.Visible = false;
            this.InvalidatePage();
        }

        private void Bar_Scroll(object sender, ScrollEventArgs e)
        {
            this.OnScroll(e);
        }

        protected virtual void OnScroll(ScrollEventArgs e)
        {
            if (this.Scroll != null)
                this.Scroll(this, e);
        }

        #region Page Segment

        public abstract class PageSegment
        {
            public ControlPage DrawnOn
            {
                get;
                protected internal set;
            }

            public virtual Point Location
            {
                get;
                protected internal set;
            }

            public Rectangle DisplayRectangle
            {
                get;
                protected set;
            }

            public Rectangle ClientRectangle
            {
                get;
                protected set;
            }

            public Padding Padding { get; set; }

            public virtual bool Visible { get; set; }

            public virtual bool CanSelect
            {
                get { return false; }
            }

            protected Graphics Graphics
            {
                get { return this.DrawnOn.Graphics; }
            }

            public abstract string Name { get; }

            public abstract void ResizeTo(Size size);

            public abstract void RenderSegment(Rectangle clip);

            public virtual void OnSizeChanged(Size available)
            {
                this.ResizeTo(available);
            }

            protected PageSegment FindSegment(string name)
            {
                return this.DrawnOn.Segments[name];
            }

            protected void DrawString(float x, float y, string s, IPaint p)
            {
                this.DrawnOn.Graphics.DrawString(s, this.DrawnOn.Font, p.Brush,
                    x, y, this.DrawnOn.StringFormat);
            }

        }

        #endregion

        #region Segment Collection

        public class SegmentCollection : IList, ICollection, IEnumerable, ICloneable
        {
            private ArrayList list;

            private ControlPage owner;

            public bool IsFixedSize
            {
                get { return this.list.IsFixedSize; }
            }

            public bool IsReadOnly
            {
                get { return this.list.IsReadOnly; }
            }

            public int Count
            {
                get { return this.list.Count; }
            }

            public bool IsSynchronized
            {
                get { return this.list.IsSynchronized; }
            }

            public object SyncRoot
            {
                get { return this.list.SyncRoot; }
            }

            public ControlPage Owner
            {
                get { return this.owner; }
            }

            public SegmentCollection(ControlPage owner)
            {
                this.owner = owner;
                this.list = new ArrayList();
            }

            private SegmentCollection(ControlPage owner, ArrayList list)
                : this(owner)
            {
                this.list = list;
            }

            int IList.Add(object value)
            {
                if(value is PageSegment)
                    return this.Add((PageSegment)value);
                return -1;
            }

            public int Add(PageSegment value)
            {
                int result = this.list.Add(value);
                this.owner.OnSegmentAdded(new SegmentEventArgs(value));
                return result;
            }

            public void AddRange(PageSegment[] segments)
            {
                foreach(PageSegment segment in segments)
                    this.Add(segment);
            }

            public void Clear()
            {
                this.list.Clear();
            }

            bool IList.Contains(object value)
            {
                if(value is PageSegment)
                    return this.Contains((PageSegment)value);
                return false;
            }

            public bool Contains(PageSegment value)
            {
                return this.list.Contains(value);
            }

            int IList.IndexOf(object value)
            {
                if (value is PageSegment)
                    return this.IndexOf((PageSegment)value);
                return -1;
            }

            public int IndexOf(PageSegment value)
            {
                throw new NotImplementedException();
            }

            public int IndexOfKey(string key)
            {
                for (int i = 0; i < this.list.Count; i++)
                {
                    if ((this.list[i] as PageSegment).Name.Equals(key))
                        return i;
                }
                return -1;
            }

            public void Insert(int index, object value)
            {
                throw new NotImplementedException();
            }

            void IList.Remove(object value)
            {
                if (value is PageSegment)
                    this.Remove((PageSegment)value);
            }

            public void Remove(PageSegment value)
            {
                this.list.Remove(value);
                this.owner.OnSegmentRemoved(new SegmentEventArgs(value));
                this.owner.InvalidatePage();
            }

            public void RemoveAt(int index)
            {
                this.list.RemoveAt(index);
                this.owner.InvalidatePage();
            }

            public void RemoveByKey(string key)
            {
                int i = IndexOfKey(key);
                if (i > -1)
                    this.RemoveAt(i);
            }

            object IList.this[int index]
            {
                get { return this.list[index]; }
                set { throw new InvalidOperationException(); }
            }

            public PageSegment this[int index]
            {
                get { return (PageSegment)this.list[index]; }
            }

            public PageSegment this[string index]
            {
                get
                {
                    int i = IndexOfKey(index);
                    return (i != -1)? ((PageSegment)this.list[i]) : null;
                }
            }

            public PageSegment[] Find(string key, bool searchAllChildren)
            {
                throw new NotImplementedException();
            }

            public int GetChildIndex(PageSegment child)
            {
                for (int i = 0; i < this.list.Count; i++)
                {
                    if (this.list[i].Equals(child))
                        return i;
                }
                return -1;
            }

            public SegmentCollection AsReadOnly()
            {
                return new SegmentCollection(this.owner, ArrayList.ReadOnly(this.list));
            }

            public void CopyTo(Array array, int index)
            {
                this.list.CopyTo(array, index);
            }

            public IEnumerator GetEnumerator()
            {
                return this.list.GetEnumerator();
            }

            public object Clone()
            {
                throw new NotImplementedException();
            }
        }

        #endregion
    }

    #region Old Code

    //public abstract class HexViewBase : Control, IHPage
    //{
    //    /// <summary>
    //    /// Used for storing the font size needs to be applied while drawing on the Page
    //    /// </summary>
    //    private Size mfSize;

    //    /// <summary>
    //    /// Used for storing the String Format that needs to be applied while drawing on the Page
    //    /// </summary>
    //    private StringFormat msFormat;

    //    /// <summary>
    //    /// Used for storing a collection of paint schemes that are being used by the Page
    //    /// </summary>
    //    private PaintSchemeCollection pSchemes;

    //    /// <summary>
    //    /// VisualStyleRenderer for Supproting Windows Visual Style's
    //    /// </summary>
    //    private VisualStyleRenderer vsRenderer;//private static VisualStyleRenderer visualStyleRenderer = null; 

    //    /// <summary>
    //    /// Used for storing the Area in which the content would be drawn
    //    /// </summary>
    //    private Rectangle mContentArea;//displayRect
        
    //    /// <summary>
    //    /// Used for storing the IDataSource object that will provide input data to the Page Segments
    //    /// </summary>
    //    private IDataSource mdProvider;

    //    /// <summary>
    //    /// Used for storing TextBoxState which is used in rendering the VisualStyle
    //    /// </summary>
    //    private TextBoxState mtbState; // TextBoxState.Normal

    //    private HScrollBar hScrollBar;

    //    private VScrollBar vScrollBar;

    //    /// <summary>
    //    /// Used for storing VisualStyleElement which is used in rendering the VisualStyle
    //    /// </summary>
    //    private static readonly VisualStyleElement tbElement = VisualStyleElement.TextBox.TextEdit.Normal;

    //    private Graphics mGraphics;

    //    private Dictionary<int, IPageSegment> mPSegments;

    //    private int mSegmentCount;

    //    private bool mdLayerZero;

    //    private bool msOverflow;

    //    private int mOverflow;

    //    protected OffsetStatesEnumerable mosEnumerable;

    //    private CaretManger mCaretManger;

    //    ///// <summary>
    //    ///// Used for storing Padding of the page
    //    ///// </summary>
    //    //private Padding Padding;

    //    private IController mController;

    //    #region IPage Propertie's

    //    Size IPage.FontSize
    //    {
    //        get { return this.mfSize; }
    //    }

    //    StringFormat IPage.StringFormat
    //    {
    //        get { return this.msFormat; }
    //    }

    //    public Size PageSize { get; private set; }

    //    [Browsable(false)]
    //    public virtual PaintSchemeCollection PaintSchemes
    //    {
    //        get { return this.pSchemes; }
    //    }

    //    Graphics IPage.Graphics
    //    {
    //        get { return this.mGraphics; }
    //    }

    //    #endregion

    //    [Browsable(false)]
    //    public virtual IDataSource Source
    //    {
    //        get { return this.mdProvider; }
    //        set
    //        {
    //            this.mdProvider = value;
    //            this.OnDataSourceChanged(EventArgs.Empty);
    //        }
    //    }

    //    [Browsable(false)]
    //    public virtual IController Controller
    //    {
    //        get { return this.mController; }
    //        set { this.Register(value); }
    //    }

    //    [Browsable(false)]
    //    public Table Table
    //    {
    //        get;
    //        private set;
    //    }

    //    [DefaultValue(gKodes.IO.DataSizes.Octet)]
    //    public gKodes.IO.DataSizes DataSize { get; set; }

    //    [Browsable(false)] // TODO: On encoder change validate cell size's
    //    public IDEncoder Encoder { get; set; }

    //    public Encoding Encoding { get; set; }

    //    public new string CompanyName
    //    {
    //        get { return "gKodes (@gKodes.net)"; }
    //    }

    //    public override Color ForeColor
    //    {
    //        get { return this.pSchemes[0].Foreground.Color; }
    //        set
    //        {
    //            this.pSchemes[0] = new PaintScheme((SolidPaint)value, (SolidPaint)base.BackColor);
    //            base.ForeColor = value;
    //        }
    //    }

    //    public override Color BackColor
    //    {
    //        get { return this.pSchemes[0].Background.Color; }
    //        set
    //        {
    //            this.pSchemes[0] = new PaintScheme((SolidPaint)base.ForeColor, (SolidPaint)value);
    //            base.BackColor = value;
    //        }
    //    }

    //    public bool HScroll
    //    {
    //        get { return this.hScrollBar.Visible; }
    //        set
    //        {
    //            if (value != this.hScrollBar.Visible)
    //            {
    //                this.hScrollBar.Visible = value;
    //                this.InvalidatePage();
    //                this.Invalidate();
    //            }
    //        }
    //    }

    //    public bool VScroll
    //    {
    //        get { return this.vScrollBar.Visible; }
    //        set
    //        {
    //            if (value != this.vScrollBar.Visible)
    //            {
    //                this.vScrollBar.Visible = value;
    //                this.InvalidatePage();
    //                this.Invalidate();
    //            }
    //        }
    //    }

    //    [Browsable(false)]
    //    public virtual bool IsOverflow
    //    {
    //        get { return this.msOverflow; }
    //        private set
    //        {
    //            if (this.msOverflow != value)
    //            {
    //                this.msOverflow = value;
    //                this.OnOverflowChanged(EventArgs.Empty);
    //            }
    //        }
    //    }

    //    public virtual int Overflow
    //    {
    //        get { return this.mOverflow; }
    //        set
    //        {
    //            if (this.mOverflow != value)
    //            {
    //                this.mOverflow = value;
    //                IHPageSegment psegment = (IHPageSegment)this.GetSegment(1);

    //                if ((psegment.DisplayRectangle.Height + value) < psegment.ClientRectangle.Height)
    //                    this.IsOverflow = true;
    //            }
    //        }
    //    }


    //    public event ScrollEventHandler Scroll
    //    {
    //        add
    //        {
    //            this.vScrollBar.Scroll += value;
    //            this.hScrollBar.Scroll += value;
    //        }
    //        remove
    //        {
    //            this.vScrollBar.Scroll -= value;
    //            this.hScrollBar.Scroll -= value;
    //        }
    //    }

    //    public event EventHandler PageSizeChanged;

    //    public event EventHandler PageInvalidated;

    //    public event EventHandler OverflowChanged;

    //    public event EventHandler DataSourceChanged;

    //    public HexViewBase()
    //    {
    //        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer |
    //            ControlStyles.UserPaint | ControlStyles.ResizeRedraw |
    //             ControlStyles.Selectable | ControlStyles.UserMouse, true);//ControlStyles.OptimizedDoubleBuffer | 

    //        this.mfSize = Size.Empty;
    //        this.mContentArea = Rectangle.Empty;
    //        this.mSegmentCount = 0;
    //        this.mdLayerZero = true;
    //        this.Padding = new Padding(2, 2, 2, 0);
    //        this.SetBoxState(TextBoxState.Normal);
    //        //this.msBars = ScrollBars.None;
    //        this.msOverflow = false;
    //        this.mOverflow = 0;

    //        this.pSchemes = new PaintSchemeCollection();
    //        this.mPSegments = new Dictionary<int, IPageSegment>();
    //        this.mosEnumerable = new OffsetStatesEnumerable();
    //        this.mCaretManger = new CaretManger(this);
            
    //        this.vScrollBar = new VScrollBar();
    //        this.vScrollBar.Name = "hv.VScrollBar";
    //        this.vScrollBar.LargeChange = 1;
    //        //this.vScrollBar.Visible = false;
    //        this.vScrollBar.VisibleChanged += new EventHandler(ScrollBarsVisibleChanged);
    //        this.hScrollBar = new HScrollBar();
    //        this.hScrollBar.Name = "hv.HScrollBar";
    //        this.hScrollBar.LargeChange = 1;
    //        //this.hScrollBar.Visible = false;
    //        this.hScrollBar.VisibleChanged += new EventHandler(ScrollBarsVisibleChanged);
            
    //        this.msFormat = StringFormat.GenericTypographic;
    //        this.msFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
    //        this.msFormat.Alignment = StringAlignment.Near;
    //        this.msFormat.LineAlignment = StringAlignment.Near;
    //        this.msFormat.Trimming = StringTrimming.Word;

    //        this.pSchemes.Change(0, new PaintScheme((SolidPaint)base.ForeColor, (SolidPaint)base.BackColor));
    //        this.pSchemes.Change(1, new PaintScheme((SolidPaint)SystemColors.HighlightText, (SolidPaint)SystemColors.Highlight));
    //        //System.Diagnostics.Debug.Fail

    //        Internals.OffsetSegment opSegment = new Internals.OffsetSegment();
    //        this.Register(opSegment);
            
    //        Internals.HexViewSegment hvSegment = new Internals.HexViewSegment();
    //        hvSegment.Padding = new Padding(2, 0, 2, 0);
    //        this.Register(hvSegment);

    //        Internals.TextSegment tSegment = new Internals.TextSegment(hvSegment);
    //        this.Register(tSegment);
			
    //        this.ChangeCellProperties(new CellProperties(new Size(8, 1), Padding.Empty), 0);
    //        this.ChangeCellProperties(new CellProperties(new Size(1, 1), Padding.Empty), 2);
    //        this.ChangeCellProperties(new CellProperties(new Size(2, 1), new Padding(5, 0, 5, 0)), 1);

    //        this.SuspendLayout();
    //        this.Controls.Add(this.vScrollBar);
    //        this.Controls.Add(this.hScrollBar);
    //        this.ResumeLayout(false);
    //    }

    //    private void ScrollBarsVisibleChanged(object sender, EventArgs e)
    //    {
            
    //    }

    //    protected override void Dispose(bool disposing)
    //    {
    //        base.Dispose(disposing);
    //        //TODO: Dispose Double buffer
    //    }

    //    #region Paint method's

    //    /// <summary>
    //    /// Helps in painting the control background
    //    /// </summary>
    //    /// <param name="clip"></param>
    //    protected virtual void PaintBackDrop(Rectangle clip)
    //    {
    //        if (VisualStyleRenderer.IsSupported)
    //            this.vsRenderer.DrawBackground(this.mGraphics, this.ClientRectangle, clip);
    //        else { this.mContentArea = this.ClientRectangle; }
    //        this.mGraphics.SetClip(clip);
    //        this.mGraphics.FillRectangle(this.pSchemes[0].Background.Brush, this.mContentArea);
    //        //this.mGraphics.FillRectangle(this.pSchemes[0].Background.Brush,
    //        //    this.mContentArea.X - this.mPPadding.Left, this.mContentArea.Y - this.mPPadding.Top, 
    //        //    this.mContentArea.Width, this.mContentArea.Height);
    //        this.mGraphics.ResetClip();
    //    }

    //    protected override void OnPaint(PaintEventArgs e)
    //    {
    //        //BufferedGraphics bGraphics = BufferedGraphicsManager.Current.Allocate(this.CreateGraphics(), this.ClientRectangle);
    //        //bGraphics.Render(
    //        this.mGraphics = e.Graphics;
    //        this.mosEnumerable.AccRange = this.mController.AccessibleRange;

    //        if (this.mdLayerZero)
    //        {
    //            this.PaintBackDrop(e.ClipRectangle);
    //            //System.Diagnostics.PerformanceCounter
    //            if (this.Source != null)
    //            {
    //                foreach (IPageSegment pSegment in this.mPSegments.Values)
    //                {
    //                    if (e.ClipRectangle.Contains(pSegment.Location))
    //                    {
    //                        this.mGraphics.TranslateTransform(pSegment.Location.X, pSegment.Location.Y);

    //                        this.mGraphics.SetClip(pSegment.DisplayRectangle);
    //                        pSegment.RenderSegment(e.ClipRectangle);

    //                        //tPoint.X += pSegment.DisplayRectangle.Width;
    //                        //if (ps.IsVertical)
    //                        //    tPoint.X += ps.DisplayRectangle.Width;
    //                        //else
    //                        //    tPoint.Y += ps.DisplayRectangle.Height;

    //                        this.mGraphics.ResetClip();
    //                        this.mGraphics.ResetTransform();
    //                    }
    //                }
    //            }
    //        }
    //        this.mCaretManger.Render(this.mGraphics);
    //        this.mGraphics = null;
    //    }

    //    #endregion

    //    protected void InvalidatePage()
    //    {
    //        if (VisualStyleRenderer.IsSupported)
    //        {
    //            this.mContentArea = this.vsRenderer.GetBackgroundContentRectangle(
    //                this.CreateGraphics(), new Rectangle(this.ClientRectangle.Location, this.PageSize));
    //        }
    //        this.mContentArea.Size -= new Size(this.Padding.Horizontal, this.Padding.Vertical);
    //        this.mContentArea.Location += new Size(this.Padding.Left, this.Padding.Top);

    //        //this.UpdateScrollBars();
    //        this.UpdateSegments();

    //        IHPageSegment psegment = (IHPageSegment)this.GetSegment(1);
    //        this.Table = psegment.Table;
    //        this.mosEnumerable.TableRange = new Range(0, this.Table.Size - 1);

    //        this.OnPageInvalidated(EventArgs.Empty);

    //        this.IsOverflow = ((psegment.DisplayRectangle.Height + this.Overflow) < psegment.ClientRectangle.Height);
    //        //if ((psegment.DisplayRectangle.Height + this.Overflow) < psegment.ClientRectangle.Height)
    //        //    this.IsOverflow = true;
    //    }

    //    /// <summary>
    //    /// Call to this method validates and updates the Scroll Bars positions
    //    /// </summary>
    //    private void UpdateScrollBars()
    //    {
    //        if (this.vScrollBar.Visible)
    //        {
    //            this.mContentArea.Width -= this.vScrollBar.Width;
    //            this.vScrollBar.Location = new Point(this.mContentArea.Right, this.mContentArea.Y);
    //            this.vScrollBar.Height = this.mContentArea.Bottom - 3;
    //        }

    //        if (this.hScrollBar.Visible)
    //        {
    //            this.mContentArea.Height -= this.hScrollBar.Height;
    //            this.hScrollBar.Location = new Point(this.mContentArea.X, this.mContentArea.Bottom);
    //            this.hScrollBar.Width = this.mContentArea.Right - 3;
    //        }
    //    }

    //    /// <summary>
    //    /// Call to this method validates and updates the Page Segments Location & Display Rectangle
    //    /// </summary>
    //    private void UpdateSegments()
    //    {
    //        Size tSize = this.mContentArea.Size;
    //        Point tPoint = this.mContentArea.Location;
    //        foreach (IPageSegment pSegment in this.mPSegments.Values)
    //        {
    //            if (pSegment.Visible)
    //            {
    //                pSegment.Location = tPoint;
    //                pSegment.OnSizeChanged(tSize);
    //                tSize.Width -= pSegment.DisplayRectangle.Width;
    //                tPoint.X += pSegment.DisplayRectangle.Width;
    //            }
    //        }
    //    }

    //    protected void SetBoxState(TextBoxState tbState)
    //    {
    //        this.mtbState = tbState;
    //        if (VisualStyleRenderer.IsSupported) {
    //            this.vsRenderer = new VisualStyleRenderer(tbElement.ClassName, tbElement.Part, (int)mtbState);
    //            this.Invalidate();
    //        }
    //    }

    //    protected void ChangeCellProperties(CellProperties cp, int p)
    //    {
    //        if (this.mPSegments[p] is IHPageSegment) {
    //            (this.mPSegments[p] as IHPageSegment).CellProperties = cp;
    //        }
    //    }

    //    #region Segment method's

    //    protected int Register(IPageSegment psegments)
    //    {
    //        this.mPSegments.Add(this.mSegmentCount, psegments);
    //        psegments.DrawnOn = this;
    //        if (psegments is IHPageSegmentN) {
    //            (psegments as IHPageSegmentN).OffsetStates = this.mosEnumerable;
    //            this.mCaretManger.RegisterCaret((IHPageSegmentN)psegments);
    //        }
    //        psegments.Visible = true;
    //        return this.mSegmentCount++;
    //    }

    //    protected void UnRegister(IPageSegment psegments)
    //    {
    //        if (this.mPSegments.ContainsValue(psegments))
    //        {
    //            //psegments.DrawnOn = null;
    //            //if (psegments is IHPageSegmentN)
    //            //    this.mCaretManger.UnRegisterCaret((IHPageSegmentN)psegments);
    //            //this.mPSegments.Remove(psegments);
    //        }
    //    }

    //    protected IPageSegment GetSegment(int psid)
    //    {
    //        return this.mPSegments[psid];
    //    }

    //    protected IPageSegment GetSegmentOfPixel(Point location)
    //    {
    //        foreach (IPageSegment psegment in this.mPSegments.Values)
    //        {
    //            if (Helper.Contains(psegment.Location, psegment.DisplayRectangle.Size, location))
    //                return psegment;
    //        }
    //        return null;
    //    }

    //    #endregion

    //    protected bool Register(IController value)
    //    {
    //        if (this.mController != null)
    //            this.mController.UnRegister();
    //        this.mController = value;
    //        if (value != null)
    //        {
    //            this.mosEnumerable.AssociatedRange = 
    //                this.mController.Register(this, this.mCaretManger);
    //        }
    //        return true;
    //    }

    //    protected bool UnRegister(IController value)
    //    {
    //        if (this.mController == value)
    //        {
    //            this.mController.UnRegister();
    //            return true;
    //        }
    //        return false;
    //    }

    //    protected override void OnFontChanged(EventArgs e)
    //    {
    //        //Encoding.GetString(new byte[] { 0 });
    //        SizeF fSize = this.CreateGraphics().MeasureString(
    //            "A", this.Font, 100, this.msFormat);
    //        this.mfSize = Size.Ceiling(fSize);

    //        this.InvalidatePage();
    //        base.OnFontChanged(e);
    //    }

    //    protected override void OnResize(EventArgs e)
    //    {
    //        this.OnPageSizeChanged(e);
    //        base.OnResize(e);
    //    }

    //    protected virtual void OnPageSizeChanged(EventArgs e)
    //    {
    //        this.PageSize = this.ClientRectangle.Size;
    //        if (this.PageSizeChanged != null)
    //            this.PageSizeChanged(this, EventArgs.Empty);
    //        this.InvalidatePage();
    //    }

    //    protected virtual void OnPageInvalidated(EventArgs e)
    //    {
    //        if (this.PageInvalidated != null)
    //            this.PageInvalidated(this, e);
    //    }

    //    /// <summary>
    //    /// Call to this method validates and updates the IsOverflow property
    //    /// </summary>
    //    protected void OnOverflowChanged(EventArgs e)
    //    {
    //        if (this.OverflowChanged != null)
    //            this.OverflowChanged(this, e);
    //    }

    //    protected virtual void OnDataSourceChanged(EventArgs e)
    //    {
    //        if (this.DataSourceChanged != null)
    //            this.DataSourceChanged(this, e);
    //    }

    //    //protected virtual void OnOffsetsStateChange(Range range, int state)
    //    //{
    //    //}

    //    #region Input Interpreter

    //    public interface IController
    //    {
    //        Range VisibleRange { get; }

    //        Range AccessibleRange { get; }

    //        bool IsRegister { get; }

    //        /// <summary>
    //        /// Get or Set the Range in which the caret can move around
    //        /// </summary>
    //        Range CaretRange { get; set; }

    //        void ValidateCaret();

    //        AssociatedRange Register(HexViewBase value, CaretManger cman);

    //        void UnRegister();
    //    }

    //    public class CaretManger : CaretManger<HexCaret>
    //    {
    //        private HexViewBase BelongsTo;

    //        public bool Visible { get; set; }

    //        public float Index
    //        {
    //            get{ return (this.Location.Y * this.BelongsTo.Table.Columns) + this.Location.X; }
    //            set { this.SetCaretPos((value / this.BelongsTo.Table)); }
    //        }

    //        public CaretManger(HexViewBase hvb)
    //            : base(hvb)
    //        {
    //            this.BelongsTo = hvb;
    //        }

    //        public override void Render(Graphics g)
    //        {
    //            if (this.Visible)
    //            {
    //                foreach (HexCaret caret in this.Carets)
    //                {
    //                    if (caret.Visible && (this.Flick || caret.Vertical))
    //                    {
    //                        g.FillRectangle(Brushes.Black, caret.BelongsTo.Location.X + caret.Location.X,
    //                                caret.BelongsTo.Location.Y + caret.Location.Y, caret.Size.Width, caret.Size.Height);
    //                    }
    //                }
    //            }
    //        }

    //        public void RegisterCaret(IHPageSegmentN psegment)
    //        {
    //            this.CreateCaret(psegment.Controler);
    //        }

    //        public void UnRegisterCaret(IHPageSegmentN psegment)
    //        {
    //            this.DestroyCaret(psegment.Controler);
    //        }
    //    }

    //    protected abstract class ControllerBase : IController
    //    {
    //        /// <summary>
    //        /// Gets the OffsetStates which is an Assocated Range Collection, which store
    //        /// all the infomation of the Offsets & there States
    //        /// </summary>
    //        internal readonly AssociatedRange OffsetStates;
            
    //        /// <summary>
    //        /// Used for storing the Range in which the caret can move around
    //        /// </summary>
    //        private Range mCRange;

    //        /// <summary>
    //        /// Used for storing the range of visible bytes those have been drawn on the screen
    //        /// </summary>
    //        private Range mVRange;

    //        private Range mARange;
            
    //        /// <summary>
    //        /// Gets the offset of the Caret
    //        /// </summary>
    //        protected double CaretOffset; // Current Caret Offset

    //        /// <summary>
    //        /// Gets the HexViewBase object to which this Controller Belongs to
    //        /// </summary>
    //        protected HexViewBase BelogsTo { get; private set; }

    //        /// <summary>
    //        /// This is used for storing a Local copy of the HexViewPainter Table Range
    //        /// </summary>
    //        private Table mhTable;

    //        /// <summary>
    //        /// This is used for storing the current line at which the caret is located
    //        /// </summary>
    //        private long mCLine;

    //        /// <summary>
    //        /// This is used for storing the last line number upto which the caret
    //        /// can move
    //        /// </summary>
    //        private long mlVLine;

    //        /// <summary>
    //        /// This is used for stroing the last Visible line n
    //        /// </summary>
    //        private int mXHeight;

    //        /// <summary>
    //        /// 
    //        /// </summary>
    //        public virtual Range VisibleRange { get { return this.mVRange; } }

    //        public virtual Range AccessibleRange { get { return this.mARange; } }

    //        public bool IsRegister { get; private set; }

    //        /// <summary>
    //        /// Get or Set the Range in which the caret can move around
    //        /// </summary>
    //        public virtual Range CaretRange
    //        {
    //            get { return this.mCRange; }
    //            set { this.mCRange = value; }
    //        }

    //        protected CaretManger CaretManger { get; private set; }
            
    //        public ControllerBase()
    //        {
    //            this.OffsetStates = new AssociatedRange();
    //        }

    //        #region Navigation method's

    //        /// <summary>
    //        /// Moves the Carets to the Stream <paramref name="offset"/> specied
    //        /// </summary>
    //        /// <param name="offset">A byte offset at which the caret should be placed</param>
    //        protected virtual void MoveToOffset(double offset)
    //        {
    //            offset = Math.Max(this.mCRange.Start, Math.Min(offset, this.mCRange.End));
    //            if (!this.VisibleRange.Contains((long)offset))
    //            {
    //                long value = (long)(offset / this.BelogsTo.Table.Columns);
    //                if ((this.mCLine + this.mXHeight) <= value)
    //                    value = (value - this.mXHeight) + ((this.BelogsTo.Table.Rows) - this.mXHeight);

    //                if (!this.MoveToLine(value))
    //                    return;
    //            }
    //            //this.CaretManger.Index = (float)(offset - this.VisibleRange.Start);
    //            this.CaretOffset = offset;
    //            this.ValidateCaret();
    //        }

    //        /// <summary>
    //        /// 
    //        /// </summary>
    //        public void ValidateCaret() //TODO: Use this function for on focus also
    //        {
    //            if ((this.CaretManger.Visible = (this.BelogsTo.Focused
    //                    && this.AccessibleRange.Contains((long)this.CaretOffset))))
    //            {
    //                this.CaretManger.Index = (float)(this.CaretOffset - this.AccessibleRange.Start);
    //            }
    //        }

    //        /// <summary>
    //        /// 
    //        /// </summary>
    //        /// <param name="value"></param>
    //        /// <returns>Returns true if successfully moved to the given line number</returns>
    //        protected bool MoveByLine(int value)
    //        {
    //            return this.MoveToLine(this.mCLine + value);
    //        }

    //        /// <summary>
    //        /// 
    //        /// </summary>
    //        /// <param name="line"></param>
    //        /// <returns>Returns true if successfully moved to the given line number</returns>
    //        protected virtual bool MoveToLine(long line)
    //        {
    //            if (this.BelogsTo.Source != null)
    //            {
    //                line = Math.Max(0, Math.Min(line, this.mlVLine));
    //                this.mARange = this.BelogsTo.Source.Load((line * this.mhTable.Columns), (int)this.mhTable.Size);

    //                if (this.mARange.Length > 0)
    //                {
    //                    this.mVRange = this.mARange;
    //                    if (this.BelogsTo.IsOverflow)
    //                        this.mVRange.Length -= this.BelogsTo.Table.Columns;
    //                    this.mCLine = line;
    //                    this.BelogsTo.vScrollBar.Value = (int)line;
    //                    this.ValidateCaret();
    //                    this.BelogsTo.Invalidate(); // TODO: when updating drawing change this
    //                    return true;
    //                }
    //            }
    //            return false;
    //        }

    //        #endregion

    //        public virtual AssociatedRange Register(HexViewBase value, CaretManger cman)
    //        {
    //            this.BelogsTo = value;
    //            this.CaretManger = cman;
    //            value.DataSourceChanged += new EventHandler(OnDataSourceChanged);
    //            value.PageInvalidated += new EventHandler(OnPageInvalidated);
    //            this.OnPageInvalidated(value, EventArgs.Empty);
    //            return this.OffsetStates;
    //        }

    //        public virtual void UnRegister()
    //        {
    //            this.BelogsTo.DataSourceChanged -= new EventHandler(OnDataSourceChanged);
    //            this.BelogsTo.PageInvalidated -= new EventHandler(OnPageInvalidated);
    //            this.CaretManger = null;
    //            this.BelogsTo = null;
    //        }

    //        #region Event Handler's

    //        protected virtual void OnDataSourceChanged(object sender, EventArgs e)
    //        {
    //            if (sender != null && sender == this.BelogsTo)
    //            {
    //                if (this.BelogsTo.Source != null)
    //                {
    //                    if (!this.IsRegister)
    //                    {
    //                        //TODO: register events
    //                        this.mCLine = 0;
    //                        this.CaretOffset = 0;
    //                        this.CaretManger.Index = 0;
    //                        this.mCRange = new Range(0, this.BelogsTo.Source.Length + 1);

    //                        this.mlVLine = (long)Math.Ceiling(
    //                            (decimal)this.BelogsTo.Source.Length / this.mhTable.Columns) - this.mXHeight;
    //                        this.BelogsTo.vScrollBar.Maximum = (int)this.mlVLine;

    //                        this.BelogsTo.GotFocus += new EventHandler(FocusChanged);
    //                        this.BelogsTo.LostFocus += new EventHandler(FocusChanged);
    //                        this.ValidateCaret();
    //                        this.mCRange = new Range(0, this.BelogsTo.Source.Length + 1);

    //                        this.BelogsTo.Scroll += new ScrollEventHandler(OnVScroll);
    //                        this.BelogsTo.MouseWheel += new MouseEventHandler(OnMouseWheel);

    //                        this.BelogsTo.ScrollBars = (this.BelogsTo.Source.Length > this.BelogsTo.Table.Size) ?
    //                            ScrollBars.Vertical : ScrollBars.None;
    //                        this.IsRegister = true;
    //                    }
    //                }
    //                else
    //                {
    //                    //TODO: unregister events
    //                    this.BelogsTo.GotFocus -= new EventHandler(FocusChanged);
    //                    this.BelogsTo.LostFocus -= new EventHandler(FocusChanged);
    //                    this.CaretManger.Visible = false;

    //                    this.BelogsTo.Scroll -= new ScrollEventHandler(OnVScroll);
    //                    this.BelogsTo.MouseWheel -= new MouseEventHandler(OnMouseWheel);
    //                }
    //            }
    //        }

    //        private void FocusChanged(object sender, EventArgs e)
    //        {
    //            this.ValidateCaret();
    //        }

    //        protected virtual void OnPageInvalidated(object sender, EventArgs e)
    //        {
    //            //TODO: calc vars max lines Update this method it looks like a mess
    //            if (this.BelogsTo.Table.Columns > 0)
    //            {
    //                this.mhTable = this.BelogsTo.Table;//
    //                this.mXHeight = this.mhTable.Rows;
                    
    //                //TODO: add 1 if there is overflow
    //                if (this.BelogsTo.IsOverflow)
    //                {
    //                    this.mXHeight -= 1;
    //                    this.mlVLine++;
    //                }
    //                this.BelogsTo.vScrollBar.Maximum = (int)this.mlVLine;
    //                this.MoveToLine(this.mCLine);// TODO: replace this with calidate caret
    //            }
    //        }

    //        protected virtual void OnVScroll(object sender, ScrollEventArgs e)
    //        {
    //            if(e.ScrollOrientation == ScrollOrientation.VerticalScroll)
    //                this.MoveToLine(e.NewValue);
    //        }

    //        protected virtual void OnMouseWheel(object sender, MouseEventArgs e)
    //        {
    //            this.MoveByLine(-1 * SystemInformation.MouseWheelScrollLines * 
    //                (e.Delta / SystemInformation.MouseWheelScrollDelta));
    //        }

    //        public virtual void AddOffsetState(Range range, int state)
    //        {
    //            this.OffsetStates.Add(range, state);
    //            this.BelogsTo.Invalidate();//TODO: Invalidate Range only
    //        }

    //        public virtual void RemoveOffsetState(Range range, int state)
    //        {
    //            this.OffsetStates.Remove(range, state);
    //            this.BelogsTo.Invalidate();//TODO: Invalidate Range only
    //            //foreach (KeyValuePair<Range, int> v in this.OffsetStates)
    //            //    System.Diagnostics.Trace.TraceInformation(v.ToString());
    //        }

    //        #endregion

    //        protected IPageSegment GetSegmentOfPixel(Point point)
    //        {
    //            return this.BelogsTo.GetSegmentOfPixel(point);
    //        }

    //    }

    //    #endregion
    //}

    #endregion
}
